package cn.latenight.http;

import org.json.JSONObject;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;

public class GetVideo {

    private static int cid;
    private static int aid;
    private static File fileVideo;

    public GetVideo(int cid, int aid, File fileVideo){
        this.cid = cid;
        this.aid = aid;
        this.fileVideo = fileVideo;
        System.out.println((char)27 + "[36m\n>>> 开始获取api中的json数据 >>>" + (char)27 + "[30m");
        getApi();
    }

    public static void getApi(){

        // https://api.bilibili.com/x/player/playurl?avid={avid}&cid={cid}&qn={resolution}&otype=json
        String spec = "https://api.bilibili.com/x/player/playurl?avid=" + aid + "+&cid=" + cid + "&qn=80&otype=json";
        try {
            URL url = new URL(spec);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("GET");

            connection.setRequestProperty("SESSDATA","b1440e19%2C1567410362%2C195d4b81");
            System.out.println("[INFO] 向请求报文中添加请求头信息：[SESSDATA:" + connection.getRequestProperty("SESSDATA") + "]");
            System.out.println("[INFO] 准备向网页发起" + connection.getRequestMethod() + "请求：" + spec);
            connection.connect();

            if (connection.getResponseCode() == 200){
                System.out.println((char)27 + "[32m[SUCCESS] 响应成功！响应行状态码：[" + connection.getResponseCode() + "]" + (char)27 + "[30m");
                InputStream is = connection.getInputStream();

                byte[] getData = readInputStream(is);
                is.read(getData);
                String json = new String(getData);
                System.out.println("[INFO] 网页：" + spec + "响应体爬取完成");
                getUrl(json);
            } else {
                System.err.println("[ERROR] 响应失败！响应行状态码：[" + connection.getResponseCode()+ "]");
                System.err.println("[ERROR] api：" + spec + "爬取失败！");
                System.err.print("[ERROR] 程序结束");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public static void getUrl(String json){

        System.out.println((char)27 + "[36m\n>>> 开始提取json数据中的视频url >>>" + (char)27 + "[30m");
        System.out.println("[INFO] json数据内容" + json);
        JSONObject jsonObject = new JSONObject(json);
        String json2 = jsonObject.optString("data");
        //http://upos-hz-mirrorcosu.acgvideo.com/upgcxcode/54/70/4517054/4517054-1-32.flv?e=ig8euxZM2rNcNbK37zUVhoMMnwuBhwdEto8g5X10ugNcXBlqNxHxNEVE5XREto8KqJZHUa6m5J0SqE85tZvEuENvNo8g2ENvNo8i8o859r1qXg8xNEVE5XREto8GuFGv2U7SuxI72X6fTr859r1qXg8gNEVE5XREto8z5JZC2X2gkX5L5F1eTX1jkXlsTXHeux_f2o859IB_\u0026uipk=5\u0026nbs=1\u0026deadline=1565725487\u0026gen=playurl\u0026os=cosu\u0026oi=3080527103\u0026trid=1cbc499617b74a2bae1701f616bca15fu\u0026platform=pc\u0026upsig=78af050cc2724850940ec68b52437c21\u0026uparams=e,uipk,nbs,deadline,gen,os,oi,trid,platform\u0026mid=0
        JSONObject jsonObject2 = new JSONObject(json2);
        String json3 = jsonObject2.optString("durl");

        String str = json3.substring(1, json3.length() - 1);

        JSONObject jsonObject3 = new JSONObject(str);
        String url = jsonObject3.optString("url");
        System.out.println((char)27 + "[32m[SUCCESS] 提取完成！视频url为：" + url + (char)27 + "[30m");
        getVideo(url);
    }

    public static void getVideo(String spec){

        System.out.println((char)27 + "[36m\n>>> 开始下载视频 >>>" + (char)27 + "[30m");
        try {
            URL url = new URL(spec);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("GET");

            connection.setRequestProperty("Referer","https://www.bilibili.com/video/av" + aid);
            System.out.println("[INFO] 向请求报文中添加请求头信息：[Referer:" + connection.getRequestProperty("Referer") + "]");
            connection.setRequestProperty("User-Agent","Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36");
            System.out.println("[INFO] 向请求报文中添加请求头信息：[User-Agent:" + connection.getRequestProperty("User-Agent") + "]");

            System.out.println("[INFO] 准备向网页发起" + connection.getRequestMethod() + "请求：" + spec);
            connection.connect();

            if(connection.getResponseCode() == 200){
                System.out.println((char)27 + "[32m[SUCCESS] 响应成功！响应行状态码：[" + connection.getResponseCode() + "]" + (char)27 + "[30m");
                InputStream is = connection.getInputStream();
                FileOutputStream fos = new FileOutputStream(fileVideo);

                System.out.println("[INFO] 网页：" + spec + "响应体爬取完成");
                System.out.println((char)27 + "[35m[WARNING] 正在将视频数据流写入文件中，不要主动关闭程序，请耐心等待..." + (char)27 + "[30m");
                byte[] bytes = new byte[5];
                int len;
                while((len = is.read(bytes)) != -1){
                    fos.write(bytes,0,len);
                }

                fos.flush();
                System.out.println((char)27 + "[32m[SUCCESS] 视频下载完毕！本地路径为：" + fileVideo.getPath() + (char)27 + "[30m");
                fos.close();
                is.close();
            } else {
                System.err.println("[ERROR] 响应失败！响应行状态码：[" + connection.getResponseCode()+ "]");
                System.err.println("[ERROR] 视频数据流：" + spec + "爬取失败！");
                System.err.print("[ERROR] 程序结束");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public static  byte[] readInputStream(InputStream inputStream) throws IOException {
        byte[] buffer = new byte[1024];
        int len = 0;
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        while((len = inputStream.read(buffer)) != -1) {
            bos.write(buffer, 0, len);
        }
        bos.close();
        return bos.toByteArray();
    }

}
